#include "postgres.h"
#include "fmgr.h"
#include "miscadmin.h"
#include "postmaster/bgworker.h"
#include "utils/elog.h"
#include "utils/builtins.h"
#include "executor/spi.h"
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(heartbeat_main);
void _PG_init(void);
void _PG_init(void) {
    BackgroundWorker worker;
    MemSet(&worker, 0, sizeof(BackgroundWorker));
    worker.bgw_flags = BGWORKER_SHMEM_ACCESS| BGWORKER_BACKEND_DATABASE_CONNECTION;
    worker.bgw_start_time = BgWorkerStart_ConsistentState;
    worker.bgw_restart_time = BGW_DEFAULT_RESTART_INTERVAL;
    snprintf(worker.bgw_name, BGW_MAXLEN, "Heartbeat Worker");
    
    strncpy(worker.bgw_library_name, "heartbeat", BGW_MAXLEN);
    strncpy(worker.bgw_function_name, "heartbeat_main", BGW_MAXLEN);
    worker.bgw_main_arg = (Datum) 0;
    worker.bgw_notify_pid = 0;
    RegisterBackgroundWorker(&worker);
}
Datum heartbeat_main(PG_FUNCTION_ARGS) {
    elog(LOG, "Starting heartbeat update");
    BackgroundWorkerUnblockSignals();//1
    BackgroundWorkerInitializeConnection("postgres", NULL, 0);
    while (true) {
        SetCurrentStatementStartTimestamp();
        StartTransactionCommand();//2
        int ret;
        if (SPI_connect() != SPI_OK_CONNECT)
            elog(ERROR, "Failed to connect to SPI");
        PushActiveSnapshot(GetTransactionSnapshot());//3
        ret = SPI_execute("UPDATE heartbeat SET last_heartbeat = now() WHERE id = 1", false, 0);//4
        
        if (ret != SPI_OK_UPDATE && ret != SPI_OK_DELETE)  // 根据 SPI 的返回码进行适当检查
            elog(WARNING, "Heartbeat update failed with code: %d", ret);
        SPI_finish();
        PopActiveSnapshot();//5
        CommitTransactionCommand();//6
        pg_usleep(1000000L);
        CHECK_FOR_INTERRUPTS();
        elog(LOG, "heartbeat update once");
    }
}
